package com.z6school.manage.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.z6school.manage.common.annotation.RequiredLog;
import com.z6school.manage.common.exception.ServiceException;
import com.z6school.manage.common.pojo.PageObject;
import com.z6school.manage.common.pojo.UserDeptVo;
import com.z6school.manage.mapper.UserMapper;
import com.z6school.manage.mapper.UserRolesMapper;
import com.z6school.manage.po.User;
import com.z6school.manage.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRolesMapper userRolesMapper;

    @Override
    @RequiredLog(operation = "查询用户信息")
    @RequiresPermissions("sys:user:view")
    public PageObject<User> findAllMessage(String username, Integer pageCurrent) {
        //1.参数校验
        if(pageCurrent == null || pageCurrent<1)
            throw new IllegalArgumentException("页码值不正确");
        //2.PageHelper
        Page<Object> page = PageHelper.startPage(pageCurrent, 5);
        List<User> userList = userMapper.selectList(null);
        //3.封装结果
        return new PageObject<User>( page.getTotal(), userList, (long) page.getPages(), 5, pageCurrent);
    }

    @Override
    @RequiredLog(operation = "更改用户状态")
    @RequiresPermissions("sys:user:type")
    public void validById(Integer id, Integer valid) {
        //1.合法性验证
        if(id==null||id<=0)
            throw new ServiceException("参数不合法,id="+id);
        if(valid==null||(valid!=1&&valid!=0))
            throw new ServiceException("参数不合法,valid="+valid);
        //2.执行禁用或启用操作(admin为后续登陆用户）
        User user = new User();
        user.setId(id).setValid(valid).setModifiedTime(new Date());
        int rows = userMapper.updateById(user);
        //3.判定结果
        if(rows==0)
            throw new ServiceException("此记录可能已经不存在");

    }

    /**保存用户对象*/
    @Override
    @RequiredLog(operation = "保存用户信息")
    @RequiresPermissions("sys:user:add")
    public int saveObject(User user, Integer[] roleIds) {
        //1.参数校验
        if(user==null)
            throw new IllegalArgumentException("保存对象不能为空");
        if(StringUtils.isEmpty(user.getUsername()))
            throw new IllegalArgumentException("用户名不能为空");
        if(StringUtils.isEmpty(user.getPassword()))
            throw new IllegalArgumentException("密码不能为空");
        if(roleIds==null || roleIds.length==0)
            throw new IllegalArgumentException("至少要为用户分配角色");
        //2.保存用户自身信息
        //2.1对密码进行加密
        String source=user.getPassword();
        String salt= UUID.randomUUID().toString();
        SimpleHash sh=new SimpleHash(//Shiro框架
                "MD5",//algorithmName 算法
                source,//原密码
                salt, //盐值
                1);//hashIterations表示加密次数
        user.setSalt(salt).setPassword(sh.toHex()).setCreatedTime(new Date()).setModifiedTime(new Date());
        int rows=userMapper.insert(user);
        //3.保存用户角色关系数据
        userRolesMapper.insertObjects(user.getId(), roleIds);
        //4.返回结果
        return rows;
    }

    /**基于id查询用户及相关信息*/
    @Override
    @RequiredLog(operation = "查询单个用户信息")
    public Map<String, Object> findObjectById(Integer userId) {
        //1.合法性验证
        if(userId==null||userId<=0)
            throw new IllegalArgumentException("参数数据不合法,userId="+userId);
        User user = userMapper.selectById(userId);
        if(user==null)
            throw new ServiceException("此用户已经不存在");
        List<Integer> roleIds = userRolesMapper.findRoleIdsByUserId(userId);
        //3.数据封装
        Map<String,Object> map=new HashMap<>();
        map.put("user", user);
        map.put("roleIds", roleIds);
        return map;
    }

    @Override
    @RequiredLog(operation = "更改用户信息")
    @RequiresPermissions("sys:user:update")
    public int updateObject(User user, Integer[] roleIds) {
        //1.参数有效性验证
        if(user==null)
            throw new IllegalArgumentException("保存对象不能为空");
        if(StringUtils.isEmpty(user.getUsername()))
            throw new IllegalArgumentException("用户名不能为空");
        if(roleIds==null||roleIds.length==0)
            throw new IllegalArgumentException("必须为其指定角色");
        //其它验证自己实现，例如用户名已经存在，密码长度，...
        //2.更新用户自身信息
        user.setModifiedTime(new Date());
        int rows = userMapper.updateById(user);
        //3.保存用户与角色关系数据
        userRolesMapper.deleteObjectByUserId(user.getId());
        userRolesMapper.insertObjects(user.getId(), roleIds);
        //4.返回结果
        return rows;
    }

    @Override
    @RequiredLog(operation = "更改用户密码")
    @RequiresPermissions("sys:user:updatePassword")
    public int updatePassword(String password, String newPassword,
                              String cfgPassword) {
        //1.判定新密码与密码确认是否相同
        if(StringUtils.isEmpty(newPassword))
            throw new IllegalArgumentException("新密码不能为空");
        if(StringUtils.isEmpty(cfgPassword))
            throw new IllegalArgumentException("确认密码不能为空");
        if(!newPassword.equals(cfgPassword))
            throw new IllegalArgumentException("两次输入的密码不相等");
        //2.判定原密码是否正确
        if(StringUtils.isEmpty(password))
            throw new IllegalArgumentException("原密码不能为空");
        //获取登陆用户
        User user=(User) SecurityUtils.getSubject().getPrincipal();
        SimpleHash sh=new SimpleHash("MD5",
                password, user.getSalt(), 1);
        if(!user.getPassword().equals(sh.toHex()))
            throw new IllegalArgumentException("原密码不正确");
        //3.对新密码进行加密
        String salt=UUID.randomUUID().toString();
        sh=new SimpleHash("MD5",newPassword,salt, 1);
        //4.将新密码加密以后的结果更新到数据库
        int rows=userMapper.updatePassword(sh.toHex(), salt,user.getId());
        if(rows==0)
            throw new ServiceException("修改失败");
        return rows;
    }

}
